package com.tinckay.common.exception;

import com.baomidou.mybatisplus.extension.api.IErrorCode;
import com.baomidou.mybatisplus.extension.api.R;
import com.tinckay.common.constant.ResultEnum;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.session.ExpiredSessionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 通用 Api Controller 全局异常处理
 * </p>
 *
 * @author yuanjie
 */
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice
public class GlobalExceptionHandler {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(ServiceException.class)
    public R service(ServiceException e) {
        IErrorCode resultEnum = e.getResultEnum();
        if (resultEnum != null) {
            log.warn("ServiceException cause,{}", resultEnum);
            return R.failed(resultEnum);
        }
        log.warn("ServiceException cause,{}", e.getMessage());
        return R.failed(e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R methodArgumentNotValid(MethodArgumentNotValidException e) {
        String errorMessage = e
                .getBindingResult()
                .getFieldError()
                .getDefaultMessage();
        return R.failed(errorMessage);
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public R noHandlerFound(NoHandlerFoundException e, HttpServletRequest request) {
        log.warn("接口 [" + request.getRequestURI() + "] 不存在,cause:{}", e.getMessage());
        return R.failed("接口 [" + request.getRequestURI() + "] 不存在");
    }

    @ExceptionHandler(ServletException.class)
    public R servlet(ServletException e) {
        log.warn("cause:{}", e.getMessage());
        return R.failed(e.getMessage());
    }

    @ExceptionHandler(MultipartException.class)
    public R multipart(MultipartException e) {
        log.warn("cause:{}", e.getMessage());
        return R.failed(e.getMessage());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R httpMessageNotReadable(HttpMessageNotReadableException e) {
        log.warn("参数异常:{}", e.getMessage());
        return R.failed(e.getMessage());
    }

    @ExceptionHandler(value = AuthorizationException.class)
    public R handleAuthorizationException() {
        return R.failed("暂无权限，请联系管理员！");
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R notFount(Exception e) {
        log.warn("Error: handleBadRequest StackTrace : {}", e);
        return R.failed(e.getMessage());
    }

}
